﻿using System;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using V2TEK.NET.SH.Silverlight.Charts.Core.Schedule;
using System.Collections.Generic;
using System.Collections.ObjectModel;

namespace V2TEK.NET.SH.Silverlight.Charts.TimeLineHelper
{
    public class TimeLineLayout : TimeLayout<TimeLineLayoutItem>
    {
        public static readonly DependencyProperty MinDateTimeRangeWidthProperty = DependencyProperty.Register("MinDateTimeRangeWidth", typeof(double), typeof(TimeLineLayout), new PropertyMetadata(80d));

        public double MinDateTimeRangeWidth
        {
            get
            {
                return (double)GetValue(MinDateTimeRangeWidthProperty);
            }
            set
            {
                SetValue(MinDateTimeRangeWidthProperty, value);
            }
        }
        public Dictionary<IDateTimeDescriptor, int> DateTimeDescriptors { get; set; }

        public override void Update()
        {
            CalculateItems();

            //Layout更新后，调用Update驱动Viewer更新UI
            base.Update();
        }

        public DateTimeType CurrentDateTimeType
        {
            get
            {
                if (this.Items != null && this.Items.Count > 0)
                    return (this.Items[0].Data as IDateTimeDescriptor).DateTimeType;
                return DateTimeType.InValid;
            }
        }

        private DateTime EnsurePreDate(DateTimeType type, DateTime date)
        {
            return date.EnsurePreDate(type);
        }

        protected void CalculateItems()
        {
            if (double.IsInfinity(XPosition) || double.IsNaN(XPosition))
                return;
            double totalMilliseconds = base.TotalMilliseconds;
            double zoom = base.Zoom;

            DateTime CurrentDate = StartDate.AddMilliseconds(XPosition);

            IDateTimeDescriptor entry = null;
            if (this.DateTimeDescriptors == null || this.DateTimeDescriptors.Count == 0)
                entry = DateTimeRangeDescriptorUtil.GetDateTimeRangeDescriptor(MinDateTimeRangeWidth, zoom);
            else
                entry = DateTimeRangeDescriptorUtil.GetDateTimeRangeDescriptor(DateTimeDescriptors,MinDateTimeRangeWidth,zoom);

            //为防止内容过多导致内存溢出，仅绘制Viewport中的items
            //----------清空Layout中的Items
            if (this.Items == null)
                this.Items = new ObservableCollection<TimeLineLayoutItem>();
            else
                this.Items.Clear();

            //----------根据ViewPort的大小重新生成Layout中的Items
            DateTime calcDate = EnsurePreDate(entry.DateTimeType, CurrentDate);
            DateTime endVisableDate = this.StartDate.AddMilliseconds(XPosition + ViewPortWidth * zoom);

            TimeLineLayoutItem item = new TimeLineLayoutItem();
            IDateTimeDescriptor itemEntry = entry.Clone();
            itemEntry.Date = calcDate;
            item.Width = calcDate.GetDateTimeRange(entry.DateTimeType, entry.Range).TotalMilliseconds;
            item.Height = ViewPortHeight;
            item.X = calcDate.Subtract(StartDate).TotalMilliseconds;
            item.Y = 0;
            item.Data = itemEntry;
            this.Items.Add(item);
            calcDate = calcDate.Add(entry.DateTimeType, entry.Range);

            //Maybe good to chart performance
            if (entry.DateTimeType.IsUnChangeRange())
            {
                while (calcDate < endVisableDate)
                {
                    TimeLineLayoutItem newItem = item.Clone();
                    newItem.X += item.Width;//calcDate.GetDateTimeRange(entry.DateTimeType, entry.Range).TotalMilliseconds;
                    newItem.Width = item.Width;
                    newItem.Data.Date = calcDate;
                    this.Items.Add(newItem);
                    item = newItem;
                    calcDate = calcDate.Add(entry.DateTimeType, entry.Range);
                }
            }
            else
            {
                while (calcDate < endVisableDate)
                {
                    TimeLineLayoutItem newItem = item.Clone();
                    newItem.X += item.Width;
                    newItem.Width = calcDate.GetDateTimeRange(entry.DateTimeType, entry.Range).TotalMilliseconds;
                    newItem.Data.Date = calcDate;
                    this.Items.Add(newItem);
                    item = newItem;
                    calcDate = calcDate.Add(entry.DateTimeType, entry.Range);
                }
            }
        }
    }
}
